home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2007 September / PCWSEP07.iso / Software / Linux / Linux Mint 3.0 Light / LinuxMint-3.0-Light.iso / casper / filesystem.squashfs / usr / share / gettext / intl / bindtextdom.c next >
Encoding:
C/C++ Source or Header  |  2007-03-05  |  9.3 KB  |  358 lines

  1. /* Implementation of the bindtextdomain(3) function
  2.    Copyright (C) 1995-1998, 2000-2003, 2005-2006 Free Software Foundation, Inc.
  3.  
  4.    This program is free software; you can redistribute it and/or modify it
  5.    under the terms of the GNU Library General Public License as published
  6.    by the Free Software Foundation; either version 2, or (at your option)
  7.    any later version.
  8.  
  9.    This program is distributed in the hope that it will be useful,
  10.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  12.    Library General Public License for more details.
  13.  
  14.    You should have received a copy of the GNU Library General Public
  15.    License along with this program; if not, write to the Free Software
  16.    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
  17.    USA.  */
  18.  
  19. #ifdef HAVE_CONFIG_H
  20. # include <config.h>
  21. #endif
  22.  
  23. #include <stddef.h>
  24. #include <stdlib.h>
  25. #include <string.h>
  26.  
  27. #include "gettextP.h"
  28. #ifdef _LIBC
  29. # include <libintl.h>
  30. #else
  31. # include "libgnuintl.h"
  32. #endif
  33.  
  34. /* Handle multi-threaded applications.  */
  35. #ifdef _LIBC
  36. # include <bits/libc-lock.h>
  37. # define gl_rwlock_define __libc_rwlock_define
  38. # define gl_rwlock_wrlock __libc_rwlock_wrlock
  39. # define gl_rwlock_unlock __libc_rwlock_unlock
  40. #else
  41. # include "lock.h"
  42. #endif
  43.  
  44. /* The internal variables in the standalone libintl.a must have different
  45.    names than the internal variables in GNU libc, otherwise programs
  46.    using libintl.a cannot be linked statically.  */
  47. #if !defined _LIBC
  48. # define _nl_default_dirname libintl_nl_default_dirname
  49. # define _nl_domain_bindings libintl_nl_domain_bindings
  50. #endif
  51.  
  52. /* Some compilers, like SunOS4 cc, don't have offsetof in <stddef.h>.  */
  53. #ifndef offsetof
  54. # define offsetof(type,ident) ((size_t)&(((type*)0)->ident))
  55. #endif
  56.  
  57. /* @@ end of prolog @@ */
  58.  
  59. /* Contains the default location of the message catalogs.  */
  60. extern const char _nl_default_dirname[];
  61. #ifdef _LIBC
  62. libc_hidden_proto (_nl_default_dirname)
  63. #endif
  64.  
  65. /* List with bindings of specific domains.  */
  66. extern struct binding *_nl_domain_bindings;
  67.  
  68. /* Lock variable to protect the global data in the gettext implementation.  */
  69. gl_rwlock_define (extern, _nl_state_lock attribute_hidden)
  70.  
  71.  
  72. /* Names for the libintl functions are a problem.  They must not clash
  73.    with existing names and they should follow ANSI C.  But this source
  74.    code is also used in GNU C Library where the names have a __
  75.    prefix.  So we have to make a difference here.  */
  76. #ifdef _LIBC
  77. # define BINDTEXTDOMAIN __bindtextdomain
  78. # define BIND_TEXTDOMAIN_CODESET __bind_textdomain_codeset
  79. # ifndef strdup
  80. #  define strdup(str) __strdup (str)
  81. # endif
  82. #else
  83. # define BINDTEXTDOMAIN libintl_bindtextdomain
  84. # define BIND_TEXTDOMAIN_CODESET libintl_bind_textdomain_codeset
  85. #endif
  86.  
  87. /* Specifies the directory name *DIRNAMEP and the output codeset *CODESETP
  88.    to be used for the DOMAINNAME message catalog.
  89.    If *DIRNAMEP or *CODESETP is NULL, the corresponding attribute is not
  90.    modified, only the current value is returned.
  91.    If DIRNAMEP or CODESETP is NULL, the corresponding attribute is neither
  92.    modified nor returned.  */
  93. static void
  94. set_binding_values (const char *domainname,
  95.             const char **dirnamep, const char **codesetp)
  96. {
  97.   struct binding *binding;
  98.   int modified;
  99.  
  100.   /* Some sanity checks.  */
  101.   if (domainname == NULL || domainname[0] == '\0')
  102.     {
  103.       if (dirnamep)
  104.     *dirnamep = NULL;
  105.       if (codesetp)
  106.     *codesetp = NULL;
  107.       return;
  108.     }
  109.  
  110.   gl_rwlock_wrlock (_nl_state_lock);
  111.  
  112.   modified = 0;
  113.  
  114.   for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next)
  115.     {
  116.       int compare = strcmp (domainname, binding->domainname);
  117.       if (compare == 0)
  118.     /* We found it!  */
  119.     break;
  120.       if (compare < 0)
  121.     {
  122.       /* It is not in the list.  */
  123.       binding = NULL;
  124.       break;
  125.     }
  126.     }
  127.  
  128.   if (binding != NULL)
  129.     {
  130.       if (dirnamep)
  131.     {
  132.       const char *dirname = *dirnamep;
  133.  
  134.       if (dirname == NULL)
  135.         /* The current binding has be to returned.  */
  136.         *dirnamep = binding->dirname;
  137.       else
  138.         {
  139.           /* The domain is already bound.  If the new value and the old
  140.          one are equal we simply do nothing.  Otherwise replace the
  141.          old binding.  */
  142.           char *result = binding->dirname;
  143.           if (strcmp (dirname, result) != 0)
  144.         {
  145.           if (strcmp (dirname, _nl_default_dirname) == 0)
  146.             result = (char *) _nl_default_dirname;
  147.           else
  148.             {
  149. #if defined _LIBC || defined HAVE_STRDUP
  150.               result = strdup (dirname);
  151. #else
  152.               size_t len = strlen (dirname) + 1;
  153.               result = (char *) malloc (len);
  154.               if (__builtin_expect (result != NULL, 1))
  155.             memcpy (result, dirname, len);
  156. #endif
  157.             }
  158.  
  159.           if (__builtin_expect (result != NULL, 1))
  160.             {
  161.               if (binding->dirname != _nl_default_dirname)
  162.             free (binding->dirname);
  163.  
  164.               binding->dirname = result;
  165.               modified = 1;
  166.             }
  167.         }
  168.           *dirnamep = result;
  169.         }
  170.     }
  171.  
  172.       if (codesetp)
  173.     {
  174.       const char *codeset = *codesetp;
  175.  
  176.       if (codeset == NULL)
  177.         /* The current binding has be to returned.  */
  178.         *codesetp = binding->codeset;
  179.       else
  180.         {
  181.           /* The domain is already bound.  If the new value and the old
  182.          one are equal we simply do nothing.  Otherwise replace the
  183.          old binding.  */
  184.           char *result = binding->codeset;
  185.           if (result == NULL || strcmp (codeset, result) != 0)
  186.         {
  187. #if defined _LIBC || defined HAVE_STRDUP
  188.           result = strdup (codeset);
  189. #else
  190.           size_t len = strlen (codeset) + 1;
  191.           result = (char *) malloc (len);
  192.           if (__builtin_expect (result != NULL, 1))
  193.             memcpy (result, codeset, len);
  194. #endif
  195.  
  196.           if (__builtin_expect (result != NULL, 1))
  197.             {
  198.               if (binding->codeset != NULL)
  199.             free (binding->codeset);
  200.  
  201.               binding->codeset = result;
  202.               modified = 1;
  203.             }
  204.         }
  205.           *codesetp = result;
  206.         }
  207.     }
  208.     }
  209.   else if ((dirnamep == NULL || *dirnamep == NULL)
  210.        && (codesetp == NULL || *codesetp == NULL))
  211.     {
  212.       /* Simply return the default values.  */
  213.       if (dirnamep)
  214.     *dirnamep = _nl_default_dirname;
  215.       if (codesetp)
  216.     *codesetp = NULL;
  217.     }
  218.   else
  219.     {
  220.       /* We have to create a new binding.  */
  221.       size_t len = strlen (domainname) + 1;
  222.       struct binding *new_binding =
  223.     (struct binding *) malloc (offsetof (struct binding, domainname) + len);
  224.  
  225.       if (__builtin_expect (new_binding == NULL, 0))
  226.     goto failed;
  227.  
  228.       memcpy (new_binding->domainname, domainname, len);
  229.  
  230.       if (dirnamep)
  231.     {
  232.       const char *dirname = *dirnamep;
  233.  
  234.       if (dirname == NULL)
  235.         /* The default value.  */
  236.         dirname = _nl_default_dirname;
  237.       else
  238.         {
  239.           if (strcmp (dirname, _nl_default_dirname) == 0)
  240.         dirname = _nl_default_dirname;
  241.           else
  242.         {
  243.           char *result;
  244. #if defined _LIBC || defined HAVE_STRDUP
  245.           result = strdup (dirname);
  246.           if (__builtin_expect (result == NULL, 0))
  247.             goto failed_dirname;
  248. #else
  249.           size_t len = strlen (dirname) + 1;
  250.           result = (char *) malloc (len);
  251.           if (__builtin_expect (result == NULL, 0))
  252.             goto failed_dirname;
  253.           memcpy (result, dirname, len);
  254. #endif
  255.           dirname = result;
  256.         }
  257.         }
  258.       *dirnamep = dirname;
  259.       new_binding->dirname = (char *) dirname;
  260.     }
  261.       else
  262.     /* The default value.  */
  263.     new_binding->dirname = (char *) _nl_default_dirname;
  264.  
  265.       if (codesetp)
  266.     {
  267.       const char *codeset = *codesetp;
  268.  
  269.       if (codeset != NULL)
  270.         {
  271.           char *result;
  272.  
  273. #if defined _LIBC || defined HAVE_STRDUP
  274.           result = strdup (codeset);
  275.           if (__builtin_expect (result == NULL, 0))
  276.         goto failed_codeset;
  277. #else
  278.           size_t len = strlen (codeset) + 1;
  279.           result = (char *) malloc (len);
  280.           if (__builtin_expect (result == NULL, 0))
  281.         goto failed_codeset;
  282.           memcpy (result, codeset, len);
  283. #endif
  284.           codeset = result;
  285.         }
  286.       *codesetp = codeset;
  287.       new_binding->codeset = (char *) codeset;
  288.     }
  289.       else
  290.     new_binding->codeset = NULL;
  291.  
  292.       /* Now enqueue it.  */
  293.       if (_nl_domain_bindings == NULL
  294.       || strcmp (domainname, _nl_domain_bindings->domainname) < 0)
  295.     {
  296.       new_binding->next = _nl_domain_bindings;
  297.       _nl_domain_bindings = new_binding;
  298.     }
  299.       else
  300.     {
  301.       binding = _nl_domain_bindings;
  302.       while (binding->next != NULL
  303.          && strcmp (domainname, binding->next->domainname) > 0)
  304.         binding = binding->next;
  305.  
  306.       new_binding->next = binding->next;
  307.       binding->next = new_binding;
  308.     }
  309.  
  310.       modified = 1;
  311.  
  312.       /* Here we deal with memory allocation failures.  */
  313.       if (0)
  314.     {
  315.     failed_codeset:
  316.       if (new_binding->dirname != _nl_default_dirname)
  317.         free (new_binding->dirname);
  318.     failed_dirname:
  319.       free (new_binding);
  320.     failed:
  321.       if (dirnamep)
  322.         *dirnamep = NULL;
  323.       if (codesetp)
  324.         *codesetp = NULL;
  325.     }
  326.     }
  327.  
  328.   /* If we modified any binding, we flush the caches.  */
  329.   if (modified)
  330.     ++_nl_msg_cat_cntr;
  331.  
  332.   gl_rwlock_unlock (_nl_state_lock);
  333. }
  334.  
  335. /* Specify that the DOMAINNAME message catalog will be found
  336.    in DIRNAME rather than in the system locale data base.  */
  337. char *
  338. BINDTEXTDOMAIN (const char *domainname, const char *dirname)
  339. {
  340.   set_binding_values (domainname, &dirname, NULL);
  341.   return (char *) dirname;
  342. }
  343.  
  344. /* Specify the character encoding in which the messages from the
  345.    DOMAINNAME message catalog will be returned.  */
  346. char *
  347. BIND_TEXTDOMAIN_CODESET (const char *domainname, const char *codeset)
  348. {
  349.   set_binding_values (domainname, NULL, &codeset);
  350.   return (char *) codeset;
  351. }
  352.  
  353. #ifdef _LIBC
  354. /* Aliases for function names in GNU C Library.  */
  355. weak_alias (__bindtextdomain, bindtextdomain);
  356. weak_alias (__bind_textdomain_codeset, bind_textdomain_codeset);
  357. #endif
  358.